package com.whpost.service.service.t;


import com.alibaba.fastjson.JSONObject;
import com.whpost.service.dao.t.MyDao;
import com.whpost.service.dao.t.TFilesMapper;
import com.whpost.service.entity.t.TFiles;

import com.whpost.service.service.BaseServices;
import com.whpost.service.tools.ToolBean;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author: Yin Zhuoyi
 * @Date: 2021/3/9 8:54
 */
@Service
public class FileService extends BaseServices<TFilesMapper, TFiles> {

    @Transactional
    public Long uploadFile(MultipartFile file, String czyId) {
        try{

            Calendar now = Calendar.getInstance();

            if (StringUtils.isEmpty(file.getOriginalFilename())) {
                throw new RuntimeException("文件上传发生错误!文件流丢失！");
            }

            //原文件名
            String fileName = file.getOriginalFilename();

            long size = file.getSize();
            DecimalFormat df = new DecimalFormat("#.00");
            String fileSizeString;
            if (size < 1024) {
                fileSizeString = df.format((double) size) + "B";
            } else if (size < 1048576) {
                fileSizeString = df.format((double) size / 1024) + "KB";
            } else if (size < 1073741824) {
                fileSizeString = df.format((double) size / 1048576) + "MB";
            } else {
                fileSizeString = df.format((double) size / 1073741824) + "GB";
            }

            String hz = fileName.substring(fileName.lastIndexOf("."));
            String ywjm = fileName.substring(0,fileName.lastIndexOf("."));
            String wjm = String.valueOf(new Date().getTime())+"_"+ToolBean.getRandomString(8)+hz;

            ToolBean.info("uploadFile的fileName:"+fileName);

            OutputStream os = null;
            InputStream inputStream = null;
            inputStream = file.getInputStream();
            String os1 = System.getProperty("os.name");

            String picPathReal="";
            if(os1!=null&&os1.contains("Windows")){
                picPathReal="d:\\wx\\files\\"+czyId+"\\"+now.get(Calendar.YEAR)+"\\"+(now.get(Calendar.MONTH) + 1)+"\\"+now.get(Calendar.DAY_OF_MONTH)+"\\";
            }else{
                //linux
                picPathReal="/home/wx/files/"+czyId+"/"+now.get(Calendar.YEAR)+"/"+(now.get(Calendar.MONTH) + 1)+"/"+now.get(Calendar.DAY_OF_MONTH)+"/";
            }
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流保存到本地文件
            File tempFile = new File(picPathReal);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            os = new FileOutputStream(tempFile.getPath() + File.separator +wjm);
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
            os.close();
            inputStream.close();

            //视频上传成功后，写逻辑表
            TFiles tFiles = new TFiles();
            tFiles.setCzyId(Long.parseLong(czyId));
            tFiles.setCfwjm(wjm);
            tFiles.setYwjm(ywjm);
            tFiles.setYwjhz(hz);
            tFiles.setWjdx(fileSizeString);
            tFiles.setWjdz(picPathReal);
            getBaseMapper().insert(tFiles);
            return tFiles.getId();
        }catch (Exception e){
            ToolBean.info("uploadFile："+e.toString());
            throw new RuntimeException("文件上传发生错误!"+e.toString());
        }
    }

    public Long uploadFile(File file, String czyId) {
        try{

            Calendar now = Calendar.getInstance();

            if (null==file) {
                throw new RuntimeException("文件上传发生错误!文件流丢失！");
            }

            //原文件名
            String fileName = file.getName();
            ToolBean.info("uploadFile的fileName:"+fileName);
            long size = file.length();
            DecimalFormat df = new DecimalFormat("#.00");
            String fileSizeString;
            if (size < 1024) {
                fileSizeString = df.format((double) size) + "B";
            } else if (size < 1048576) {
                fileSizeString = df.format((double) size / 1024) + "KB";
            } else if (size < 1073741824) {
                fileSizeString = df.format((double) size / 1048576) + "MB";
            } else {
                fileSizeString = df.format((double) size / 1073741824) + "GB";
            }

            String hz = fileName.substring(fileName.lastIndexOf("."));
            String ywjm = fileName.substring(0,fileName.lastIndexOf("."));
            String wjm = String.valueOf(new Date().getTime())+"_"+ToolBean.getRandomString(8)+hz;

            OutputStream os = null;
            InputStream inputStream = null;
            inputStream = new FileInputStream(file);
            String os1 = System.getProperty("os.name");

            String picPathReal="";
            if(os1!=null&&os1.contains("Windows")){
                picPathReal="d:\\wx\\files\\"+czyId+"\\"+now.get(Calendar.YEAR)+"\\"+(now.get(Calendar.MONTH) + 1)+"\\"+now.get(Calendar.DAY_OF_MONTH)+"\\";
            }else{
                //linux
                picPathReal="/home/wx/files/"+czyId+"/"+now.get(Calendar.YEAR)+"/"+(now.get(Calendar.MONTH) + 1)+"/"+now.get(Calendar.DAY_OF_MONTH)+"/";
            }
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流保存到本地文件
            File tempFile = new File(picPathReal);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            os = new FileOutputStream(tempFile.getPath() + File.separator +wjm);
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
            os.close();
            inputStream.close();

            //视频上传成功后，写逻辑表
            TFiles tFiles = new TFiles();
            tFiles.setCzyId(Long.parseLong(czyId));
            tFiles.setCfwjm(wjm);
            tFiles.setYwjm(ywjm);
            tFiles.setYwjhz(hz);
            tFiles.setWjdx(fileSizeString);
            tFiles.setWjdz(picPathReal);
            getBaseMapper().insert(tFiles);
            return tFiles.getId();
        }catch (Exception e){
            ToolBean.info("uploadFile："+e.toString());
            throw new RuntimeException("文件上传发生错误!"+e.toString());
        }
    }

    /**
     * 保存文件到lj+wjm
     * @param file
     * @param lj
     * @param wjm
     * @return
     */
    public Boolean uploadFileToLj(MultipartFile file, String lj,String wjm) {
        try{
            if (null==file) {
                throw new RuntimeException("文件上传发生错误!文件流丢失！");
            }
            ToolBean.info("uploadFileToLj开始上传文件:"+file);
            OutputStream os = null;
            InputStream inputStream = null;
            inputStream = file.getInputStream();

            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流保存到本地文件
            File tempFile = new File(lj);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            ToolBean.info("uploadFileToLj准备保存到:"+lj+wjm);
            os = new FileOutputStream(lj+wjm);
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
            os.close();
            inputStream.close();

            return true;
        }catch (Exception e){
            ToolBean.info("uploadFileToLj："+e.toString());
            throw new RuntimeException("文件上传发生错误!"+e.toString());
        }
    }

    /**
     * 保存文件到lj+wjm
     * @param lj
     * @param wjm
     * @return
     */
    public Boolean uploadFileToLjSf(String lj,String wjm,String wjm1) {
        try{
            Thumbnails.of(new File(lj+wjm))
                    .size(640, 423)  //处理图片大小
                    .outputQuality(0.5f)  //压缩比例
                    .toFile(lj+wjm1);  //生成的图片的位置

            return true;
        }catch (Exception e){
            ToolBean.info("uploadFileToLjSf："+e.toString());
            throw new RuntimeException("文件上传发生错误!"+e.toString());
        }
    }

    //删除文件
    @Transactional
    public boolean delFileById(TFiles tFiles){

        try{
            //删除文件
            String lj=tFiles.getWjdz()+tFiles.getCfwjm();
            ToolBean.info("准备删除"+lj);
            File file = new File(lj);
            if (file.exists()){
                ToolBean.info("删除"+lj+"...");
                file.delete();
                ToolBean.info("删除"+lj+"完成");
                getBaseMapper().deleteById(tFiles);
            }
            return true;
        }catch (Exception e){
            throw new RuntimeException("文件上传发生错误!"+e.toString());
        }
    }

    @Transactional
    public String downloadById(String loginId, String fileId,HttpServletResponse response) throws IOException {
        if (StringUtils.isEmpty(loginId)){
            throw new RuntimeException("用户信息丢失!");
        }else{
            try {
                TFiles tFiles = new TFiles();
                tFiles = getBaseMapper().selectById(fileId);
                if (null==tFiles){
                    throw new RuntimeException("文件ID不存在!");
                }
                if ("1".equals(tFiles.getSfzj())){
                    if (!loginId.equals(String.valueOf(tFiles.getCzyId()))){
                        throw new RuntimeException("没有权限下载!");
                    }
                }
                // 根据文件名获取文件的绝对路径
                String filePath = tFiles.getWjdz()+tFiles.getCfwjm();
                File file = new File(filePath);
                if (!file.exists()) {
                    throw new RuntimeException("文件位置不存在!"+filePath);
                }
                ToolBean.info("准备下载文件:"+filePath+",下载文件名【"+tFiles.getYwjm()+tFiles.getYwjhz()+"】");
                // 指定要下载的文件
                //文件名编码，防止中文乱码
                String filename = URLEncoder.encode(tFiles.getYwjm()+tFiles.getYwjhz(), "UTF-8");
                // 设置响应头信息
                response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
                // 内容类型为通用类型，表示二进制数据流
                response.setContentType("application/octet-stream");
                // 循环，边读取边输出，可避免大文件时OOM
                try (InputStream inputStream = new FileInputStream(file); OutputStream os = response.getOutputStream()) {
                    byte[] bytes = new byte[1024];
                    int readLength;
                    while ((readLength = inputStream.read(bytes)) != -1) {
                        os.write(bytes, 0, readLength);
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException("文件下载发生错误!"+e.toString());
            }
        }
        return "";
    }

    @Transactional
    public String downloadApk(HttpServletResponse response) throws IOException {
        try {
            String apkDz = getMyDao().getCsz("APK");
            ToolBean.info("apkdz:"+apkDz);
            if (StringUtils.isEmpty(apkDz)){
                throw new RuntimeException("文件不存在!");
            }
            // 根据文件名获取文件的绝对路径
            File file = new File(apkDz);
            if (!file.exists()) {
                throw new RuntimeException("文件位置不存在!");
            }
            // 指定要下载的文件
            //文件名编码，防止中文乱码
            String filename = URLEncoder.encode("hsbg.apk", "UTF-8");
            // 设置响应头信息
            response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
            // 内容类型为通用类型，表示二进制数据流
            response.setContentType("application/octet-stream");
            // 循环，边读取边输出，可避免大文件时OOM
            try (InputStream inputStream = new FileInputStream(file); OutputStream os = response.getOutputStream()) {
                byte[] bytes = new byte[1024];
                int readLength;
                while ((readLength = inputStream.read(bytes)) != -1) {
                    os.write(bytes, 0, readLength);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException("文件下载发生错误!"+e.toString());
        }
        return "";
    }

    /**
     *
     * @param wj
     * @param lj
     * @param wjm
     * @return
     */
    public boolean uploadFileSlt(MultipartFile wj, String lj,String wjm,String wjm1) {
        OutputStream os = null;
        InputStream inputStream = null;
        String ywj = null;
        try {
            inputStream = wj.getInputStream();
            ywj = wj.getOriginalFilename();
            String hz = ywj.substring(ywj.lastIndexOf("."));
            String ywjm = ywj.substring(0,ywj.lastIndexOf("."));
            Calendar now = Calendar.getInstance();

            String os1 = System.getProperty("os.name");

            ToolBean.info("开始保存图片"+lj+wjm);

            // 2、保存到临时文件
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流保存到本地文件
            File tempFile = new File(lj);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            os = new FileOutputStream(lj + wjm);
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
            os.close();
            inputStream.close();

            ToolBean.info("开始保存图片"+lj+wjm+"完成，准备生成缩略图["+lj+wjm1+"]");
            Thumbnails.of(new File(lj+wjm))
                    .size(640, 423)  //处理图片大小
                    .outputQuality(0.5f)  //压缩比例
                    .toFile(lj+wjm1);  //生成的图片的位置
            ToolBean.info("开始保存图片"+lj+wjm+"完成，准备生成缩略图["+lj+wjm1+"]完成");
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
